package org.openstreetmap.gui.jmapviewer;

/**
 * Created by: Eduardo Quintana Contreras
 * Date: 4/07/12
 * Time: 03:52 PM
 */

import edu.cicese.alz.GPSUtilities;
import edu.cicese.alz.swing.SwingUtil;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.List;

public class MapLocation {

	public static final int TYPE_INCIDENCES = 0;
	public static final int TYPE_TIME_SPENT = 1;
	private Font font = SwingUtil.fMap;

	private double lat;
	private double lon;
	private double minLat, maxLat;
	private double minLon, maxLon;

	private double lat1, lon1;
	private double lat2, lon2;

	private Color colorBackground, colorBorder;

	private int locationSize;
	private String label;
	private int tQuantity; //time spent
	private int mQuantity; //incidences
	private int infoType;
	private boolean showingInfo = false;
	private boolean adjustingSize = false;

	private List<MapMarker> mapMarkers = new ArrayList<>();
	private int mapLocationID;

	private boolean isHome = false;

	/*public MapLocation(double lat, double lon, Color colorBackground, Color colorBorder,
	                   double minLat, double minLon, double maxLat, double maxLon) {
		this.lat = lat;
		this.lon = lon;
		this.colorBackground = colorBackground;
		this.colorBorder = colorBorder;
		this.minLat = minLat;
		this.maxLat = maxLat;
		this.minLon = minLon;
		this.maxLon = maxLon;
	}

	public MapLocation(double lat, double lon, Color colorBackground, Color colorBorder,
	                   double minLat, double minLon, double maxLat, double maxLon, int radius) {
		this(lat, lon, colorBackground, colorBorder, minLat, minLon, maxLat, maxLon);
		this.radius = radius;
	}

	public MapLocation(double lat, double lon, Color colorBackground, Color colorBorder,
	                   double minLat, double minLon, double maxLat, double maxLon, int radius, String label) {
		this(lat, lon, colorBackground, colorBorder, minLat, minLon, maxLat, maxLon, radius);
		this.label = label;
		this.showingInfo = true;
	}

	public MapLocation(double lat, double lon, Color colorBackground, Color colorBorder,
	                   double minLat, double minLon, double maxLat, double maxLon,
	                   String label, int quantity, int infoType) {
		this(lat, lon, colorBackground, colorBorder, minLat, minLon, maxLat, maxLon, 0, label);
		this.radius = infoType == TYPE_INCIDENCES ? getRadiusFromIncidences() : getRadiusFromTimeSpent();
	}*/

	public MapLocation(double lat, double lon, Color colorBackground, Color colorBorder,
	                   double minLat, double minLon, double maxLat, double maxLon, int locationSize,
	                   int locationRadius, int mQuantity, int tQuantity, int infoType, boolean showingInfo, boolean adjustingSize) {
//		this(lat, lon, colorBackground, colorBorder, minLat, minLon, maxLat, maxLon, radius);
		this.lat = lat;
		this.lon = lon;
		this.colorBackground = colorBackground;
		this.colorBorder = colorBorder;
		this.minLat = minLat;
		this.maxLat = maxLat;
		this.minLon = minLon;
		this.maxLon = maxLon;
		this.locationSize = locationSize;
		this.tQuantity = tQuantity;
		this.mQuantity = mQuantity;
		this.infoType = infoType;
		this.adjustingSize = adjustingSize;
		this.showingInfo = showingInfo;

		double[] off1 = GPSUtilities.getLatLon(lat, lon, locationRadius * -1);
		lat1 = off1[0];
		lon1 = off1[1];

		double[] off2 = GPSUtilities.getLatLon(lat, lon, locationRadius);
		lat2 = off2[0];
		lon2 = off2[1];
	}


	public double getLat() {
        return lat;
    }

    public double getLon() {
        return lon;
    }

	public double getMinLat() {
		return minLat;
	}

	public double getMaxLat() {
		return maxLat;
	}

	public double getMinLon() {
		return minLon;
	}

	public double getMaxLon() {
		return maxLon;
	}

	public double getLat1() {
		return lat1;
	}

	public double getLon1() {
		return lon1;
	}

	public double getLat2() {
		return lat2;
	}

	public double getLon2() {
		return lon2;
	}

	public int getIncidences() {
		return mQuantity;
	}

	public int getTimeSpent() {
		return tQuantity;
	}

	public int getMapLocationID() {
		return mapLocationID;
	}

	public void setInfoType(int infoType) {
		this.infoType = infoType;
	}

	public void setShowingInfo(boolean showingInfo) {
		this.showingInfo = showingInfo;
	}

	public void setAdjustingSize(boolean adjustingSize) {
		this.adjustingSize = adjustingSize;
	}

	public void setMapLocationID(int mapLocationID) {
		this.mapLocationID = mapLocationID;
	}

	public void addMapMarkers(List<MapMarker> mapMarkers) {
		for (MapMarker mapMarker : mapMarkers) {
			mapMarker.setIsInLocation(true);
			mapMarker.setMapLocationID(mapLocationID);
			this.mapMarkers.add(mapMarker);
		}
	}


	private int getRadius(int x, int y, int minX, int minY, int maxX, int maxY) {
		int a = x - minX;
		int b = y - maxY;
		int hyp1 = (int) Math.sqrt(a * a + b * b);
		a = maxX - x;
		b = minY - y;
		int hyp2 = (int) Math.sqrt(a * a + b * b);

		if (hyp1 > hyp2) return hyp1;
		return hyp2;
	}

	private int getRadiusFromIncidences() {
		int aux = mQuantity;
		if (mQuantity > 10) aux = 10;
		return 9 + aux * 4;
	}

	private int getRadiusFromTimeSpent() {
		int aux = tQuantity;
		if (tQuantity > 80) aux = 80;
		return 9 + aux / 2;
	}


	public boolean isHome() {
		return isHome;
	}

	public void setHome(boolean home) {
		isHome = home;
	}


	public void paint(Graphics g, Point position, Point position1, Point position2, int zoom) {
		Graphics2D g2 = (Graphics2D) g;

		g2.setRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));
		g2.setFont(font);
		FontMetrics metrics = g2.getFontMetrics();

		// Calculate location size
		int radius;
		if (!adjustingSize) {
			radius = zoom > 15 ? getRadius(position.x, position.y, position1.x, position2.y, position2.x, position1.y) : locationSize;
		}
		else {
			if (infoType == TYPE_INCIDENCES) {
				radius = getRadiusFromIncidences();
			}
			else {
				radius = getRadiusFromTimeSpent();
			}
		}

//		radius = 20;
//		System.out.println("incidences " + mQuantity + " timespent " + tQuantity + " type " + infoType);

//		int radius = zoom > 15 ?
//				getRadius(position.x, position.y, position1.x, position2.y, position2.x, position1.y) : this.radius;
		int diameter = radius * 2;

		Area area = new Area(new Ellipse2D.Double(position.x - radius, position.y - radius, diameter, diameter));
		g2.setColor(colorBackground);
		g2.setStroke(new BasicStroke());
		g2.fill(area);
		g2.setColor(colorBorder);
		g2.setStroke(new BasicStroke(2));
		g2.draw(area);

		if (showingInfo) {
			String label = infoType == TYPE_INCIDENCES ? mQuantity + "" : tQuantity + "";

			int textWidth = metrics.stringWidth(label);
			int textHeight = metrics.getHeight();
			int x = position.x - textWidth / 2;
			int y = position.y + textHeight / 2 - 3;

			g2.setColor(Color.WHITE);
			g2.drawString(label, ShiftWest(x, 1), ShiftNorth(y, 1));
			g2.drawString(label, ShiftWest(x, 1), ShiftSouth(y, 1));
			g2.drawString(label, ShiftEast(x, 1), ShiftNorth(y, 1));
			g2.drawString(label, ShiftEast(x, 1), ShiftSouth(y, 1));
			g2.setColor(Color.BLACK);
			g2.drawString(label, x, y);
		}
	}


	private int ShiftNorth(int p, int distance) {
		return (p - distance);
	}

	private int ShiftSouth(int p, int distance) {
		return (p + distance);
	}

	private int ShiftEast(int p, int distance) {
		return (p + distance);
	}

	private int ShiftWest(int p, int distance) {
		return (p - distance);
	}
}

